﻿// Inner Fire 游戏引擎库
// 帧资源类
//
// Copyright (c) 2023 by 尔西大帝. All rights reserved.
//
// 这个类用于进行帧资源的操作。使CPU与GPU不需要等待同步进行操作。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2024-11-19

#pragma once

#include <dx_core/uploader_buffer.h>
#include <dx_model/material.h>

namespace ifire {

struct FrameResourceDesc {
  UINT PassCount;
  UINT ObjectCount;
  UINT MaterialCount;
  UINT WaveVertexCount;
  UINT SkinnedObjectCount;
};

struct FrameResource {
public:
  FrameResource(ID3D12Device* device, const FrameResourceDesc* desc);
  FrameResource(const FrameResource& lhs) = delete;
  FrameResource& operator=(const FrameResource& lhs) = delete;
  ~FrameResource();

  // 在GPU处理完与此命令分配器相关的命令之前，我们不能对它进行重置。
  // 所以每一帧都需要有自已的命令分配器。
  ComPtr<ID3D12CommandAllocator> CmdListAlloc;

  // 在GPU执行完此常量缓冲区的命令之前，我们不能对它进行更新
  // 所以每一帧要有它们自已的常量缓冲区
  std::unique_ptr<UploadBuffer<PassConstants>> PassCB = nullptr;
  std::unique_ptr<UploadBuffer<ObjectConstants>> ObjectCB = nullptr;
  std::unique_ptr<UploadBuffer<ObjectConstantsV2>> ObjectCB_V2 = nullptr;

  // 我们不能在GPU完成处理引用动态顶点缓冲区的命令之前更新它。
  // 因此，每个帧都需要它们自己的缓冲区。
  std::unique_ptr<UploadBuffer<Vertex>> WavesVB = nullptr;

  // 用于材质的缓冲区
  std::unique_ptr<UploadBuffer<MaterialConstants>> MaterialCB = nullptr;
  std::unique_ptr<UploadBuffer<MaterialData>> MaterialBuffer = nullptr;

  std::unique_ptr<UploadBuffer<InstanceData>> InstanceBuffer = nullptr;
  std::unique_ptr<UploadBuffer<SsaoConstants>> SsaoCB = nullptr;
  std::unique_ptr<UploadBuffer<SkinnedConstants>> SkinnedCB = nullptr;
  // 通过围栏值将命令标记到此围栏点，使我们可以检查到GPU是否还在使用此帧资源
  UINT64 Fence = 0;
};

} // namespace ifire